﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace sgca.UrlBuilder
{
    /// <summary>
    /// Builds a URL based on different parts (making sure no extra / is available)
    /// Query string processing is also available using fluent syntax.
    /// </summary>
    public class UrlBuilder
    {
        /// <summary>
        /// Contains all parts without the "/"
        /// </summary>
        private List<string> Parts { get; set; }
        private List<KeyValuePair<string, string>> QueryString { get; set; }

        public const char PATH_SEPARATOR_CHAR = '/';

        /// <summary>
        /// Creates a URL base
        /// Now supports both relative and absolute URLs (no more http:// check)
        /// </summary>
        public UrlBuilder(string baseUrl)
        {
            if (string.IsNullOrEmpty(baseUrl))
            {
                throw new ArgumentException("baseUrl is empty.");
            }

            Parts = new List<string>();
            QueryString = new List<KeyValuePair<string, string>>();

            while (baseUrl.EndsWith("" + PATH_SEPARATOR_CHAR))
            {
                baseUrl = baseUrl.Substring(0, baseUrl.Length - 1);
            }

            Parts.Add(baseUrl);
        }

        public UrlBuilder AddPart(string part)
        {
            if (!string.IsNullOrEmpty(part))
            {
                Parts.Add(StripBoth(part));
            }
            return this;
        }

        public UrlBuilder AddQueryString(string key, string value)
        {
            if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
            {
                QueryString.Add(new KeyValuePair<string, string>(key, value));
            }
            return this;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            string url = string.Join("" + PATH_SEPARATOR_CHAR, Parts.ToArray());
            List<string> queryString = QueryString.Select(s => string.Format("{0}={1}", s.Key, s.Value)).ToList();

            sb.Append(url);

            if (queryString.Count > 0)
            {
                sb.Append("?");
                foreach (string qs in queryString)
                {
                    sb.Append(qs);
                    sb.Append("&");
                }
                // If it ends with &, remove that one
                if (sb[sb.Length - 1] == '&')
                {
                    sb.Remove(sb.Length - 1, 1);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// Strips both sides of the given string of "/"es
        /// </summary>
        private string StripBoth(string part)
        {
            return part.Trim(new char[] { PATH_SEPARATOR_CHAR });
        }
    }
}
